package com.shelpe.services.algorithm.mobileQscore;

import java.math.BigDecimal;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shelpe.services.algorithm.configuration.MobileQscoreProperties;
import com.shelpe.services.algorithm.constant.MobileRank;
import com.shelpe.services.algorithm.entity.jpa.DevelopmentKeyword;
import com.shelpe.services.algorithm.entity.jpa.DevelopmentPlan;
import com.shelpe.services.algorithm.repository.jpa.DevelopmentKeywordRepository;
import com.shelpe.services.algorithm.sustain.SustainRule;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class MobileQscoreKeepingKeywordSustainRule implements SustainRule<MobileScoreKeywordSustainer> {
	@Autowired
	private DevelopmentKeywordRepository developmentKeywordRepository;
	@Autowired
	private MobileQscoreProperties prop;
	
	@Override
	public boolean check(MobileScoreKeywordSustainer entity) {
		long days = ((new Date()).getTime() - entity.getAdgroup().getCreateTime().getTime()) / (1000 * 60 * 60 *24);
		boolean keeping = days >= this.prop.getKeepingDays();
		entity.setDays(days);
		log.debug("{} keeping: {}", keeping, entity.getKeyword());
		return keeping && entity.getKeyword() != null && entity.getUserReport() != null;
	}

	@Override
	public boolean prepare(MobileScoreKeywordSustainer entity) {
		log.debug("prepare MobileQscoreKeepingKeywordSustainRule: {}", entity);
		return true;
	}

	@Override
	public SustainRule.SustainStatus sustain(MobileScoreKeywordSustainer entity) {
		SustainRule.SustainStatus ss = SustainRule.SustainStatus.keep;
		
		int mobileQscore = entity.getKeyword().getWirelessQscore() != null?entity.getKeyword().getWirelessQscore().intValue():-1;
		log.debug("keyword({} - {}) mobile qscore: {}", entity.getKeyword().getKeywordId(), entity.getKeyword().getWord(), mobileQscore);
		if(mobileQscore == -1){
			log.warn("no mobile qscore keyword({} - {}): {}", entity.getKeyword().getKeywordId(), entity.getKeyword().getWord());
		}
		
		//低质量得分, 0可能为质量分未同步
		if(mobileQscore > 0 && mobileQscore < prop.getLowMobileQscore()){
			ss = SustainRule.SustainStatus.remove;
			entity.getSnapshot().setReason("low_mobile_qscore[" + mobileQscore + "]");
			return ss;
		}
		
		if(entity.getLastReport() == null){
			return ss;
		}
		
		MobileRank lastRank = null;
		MobileRank targetRank = null;
		DevelopmentKeyword nextDev = new DevelopmentKeyword();
		
		if(entity.getRealtimeRank() != null){
			lastRank = MobileRank.from(entity.getRealtimeRank().getMoibleRank());
		}
		
		DevelopmentKeyword lastDevelopment = this.developmentKeywordRepository.findTopByKeywordIDOrderByCreatedTimeDesc(entity.getKeyword().getKeywordId());
		if(lastDevelopment != null){
			if(lastRank == null){//如果实时排名没有就那最近一次培养的排名
				lastRank = MobileRank.from(lastDevelopment.getLastRank());
			}
			if(lastDevelopment.isByPricing()){
				targetRank = MobileRank.from(lastDevelopment.getTarget());
				if(entity.getDays() == this.prop.getKeepingDays()){//如果刚进保持期，需要那当时的排名作为目标排名。
					targetRank = lastRank;
				}
			}
		}
		
		if(lastRank == null){
			lastRank = MobileRank.after20OfIndex;
		}
		if(targetRank == null){
			targetRank = MobileRank.firstOfIndex;
		}
		
		log.debug("keyword({} - {}) last rank is in the target rank range: {} == {}", 
				entity.getKeyword().getKeywordId(), entity.getKeyword().getWord(), lastRank, targetRank);
		
		float avgRoi = 0;
		if(entity.getUserReport().getCost() > 0){
			avgRoi = ((float)(entity.getUserReport().getIndirectPay() + entity.getUserReport().getDirectPay())) / entity.getUserReport().getCost();
		}
		

		if(lastRank.getValue() <= targetRank.getValue()){
			if(entity.getLastReport().getCpc() > entity.getUserReport().getCpc().floatValue()
					&& entity.getLastReport().getRoi() == 0){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-15));
			}
			if(entity.getLastReport().getCpc() > entity.getUserReport().getCpc().floatValue()
					&& entity.getLastReport().getRoi() > avgRoi){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-10));
			}
			if(entity.getLastReport().getCpc() <= entity.getUserReport().getCpc().floatValue()
					&& entity.getLastReport().getRoi() == 0){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-5));
			}
			if(entity.getLastReport().getCpc() <= entity.getUserReport().getCpc().floatValue()
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() <= avgRoi){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-5));
			}
			if(entity.getLastReport().getCpc() <= entity.getUserReport().getCpc().floatValue()
					&& entity.getLastReport().getRoi() > avgRoi){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-5));
			}
		}
		
		if(lastRank.getValue() > targetRank.getValue()){
			if(entity.getLastReport().getCpc() > (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() == 0){
				ss = SustainRule.SustainStatus.remove;
				entity.getSnapshot().setReason("zero_roi[" + entity.getLastReport().getRoi() + "]high_cpc[" + entity.getLastReport().getCpc() + "]");
			}
			if(entity.getLastReport().getCpc() > (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() <= (avgRoi * 0.7)
					&& entity.getLastReport().getCost() >= (entity.getUserReport().getCost() * 0.3)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-5));
			}
			if(entity.getLastReport().getCpc() > (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() <= (avgRoi * 0.7)
					&& entity.getLastReport().getCost() < (entity.getUserReport().getCost() * 0.3)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(0));
			}
			if(entity.getLastReport().getCpc() > (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() > (avgRoi * 0.7)
					&& entity.getLastReport().getCost() < (entity.getUserReport().getCost() * 0.3)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.digit);
				nextDev.setPremium(BigDecimal.valueOf(10));
			}
			
			
			if((entity.getUserReport().getCpc().floatValue() * 0.8) <= entity.getLastReport().getCpc() && entity.getLastReport().getCpc() < (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() == 0){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.precentage);
				nextDev.setPremium(BigDecimal.valueOf(-5));
			}
			if((entity.getUserReport().getCpc().floatValue() * 0.8) <= entity.getLastReport().getCpc() && entity.getLastReport().getCpc() < (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() <= (avgRoi * 0.7)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.digit);
				nextDev.setPremium(BigDecimal.valueOf(0));
			}
			if((entity.getUserReport().getCpc().floatValue() * 0.8) <= entity.getLastReport().getCpc() && entity.getLastReport().getCpc() < (entity.getUserReport().getCpc().floatValue() * 1.2)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() > (avgRoi * 0.7)
					&& entity.getLastReport().getCost() < (entity.getUserReport().getCost() * 0.3)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.digit);
				nextDev.setPremium(BigDecimal.valueOf(10));
			}
			
			if(entity.getLastReport().getCpc() <= (entity.getUserReport().getCpc().floatValue() * 0.8)
					&& entity.getLastReport().getRoi() > 0 && entity.getLastReport().getRoi() < (avgRoi * 0.8)){
				nextDev.setTargetType(lastDevelopment.getTargetType());
				nextDev.setTarget(lastDevelopment.getTarget());
				nextDev.setPremiumType(DevelopmentPlan.PremiumType.digit);
				nextDev.setPremium(BigDecimal.valueOf(10));
			}
		}
	
		
		
		if(nextDev.getTargetType() != null){
			ss = SustainRule.SustainStatus.ranking;
			nextDev.setLastRank(lastRank.getValue());
			nextDev.setKeywordID(entity.getKeyword().getKeywordId());
			nextDev.setWord(entity.getKeyword().getWord());
			nextDev.setOriginalValue(entity.getKeyword().getMaxMobilePrice());
			nextDev.setStatus(DevelopmentKeyword.Status.executable);
			nextDev.setCreatedTime(new Date());
			nextDev.setModifiedTime(new Date());
			entity.setDevelopmentKeyword(nextDev);
		}
		
		return ss;
	}

	@Override
	public boolean maintain(MobileScoreKeywordSustainer entity, SustainRule.SustainStatus status) {
		return true;
	}

	@Override
	public boolean mark(MobileScoreKeywordSustainer entity) {
		return true;
	}

}
